﻿//-------------------------------------------------------------------------------------------
// <copyright file="TransactionConverter.cs" company="Russell Wilkins">
//     Copyright (c) Russell Wilkins 2014. All Rights Reserved.
// </copyright>
// <author>Russell Wilkins</author>
// <license href="license.txt">
//     The use of this software is governed by the Microsoft Public License
//     which is included with this distribution.
// </license>
//-------------------------------------------------------------------------------------------
namespace Ripple.Data.Converters
{
    using Helpers;
    using Providers;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    /// <summary>
    /// TODO: Describe the class
    /// </summary>
    internal static class TransactionConverter
    {
        internal static IEnumerable<Transaction> ToEntities(this IEnumerable<TransactionData> list, IRippleContext rippleContext)
        {
            foreach (var item in list)
            {
                yield return item.ToEntity(rippleContext);
            }
        }

        internal static Transaction ToEntity(this TransactionData data, IRippleContext rippleContext)
        {
            if (data == null)
            {
                return null;
            }

            Transaction entity = null;
            switch (data.tx.TransactionType)
            {
                case "Payment":
                    {
                        entity = new PaymentTransaction(rippleContext);
                        (entity as PaymentTransaction).UpdateEntity(data);
                        break;
                    }
                case "TrustSet":
                    {
                        entity = new TrustSetTransaction(rippleContext);
                        (entity as TrustSetTransaction).UpdateEntity(data);
                        break;
                    }
                case "OfferCreate":
                    {
                        entity = new OfferCreateTransaction(rippleContext);
                        (entity as OfferCreateTransaction).UpdateEntity(data);
                        break;
                    }
                case "OfferCancel":
                    {
                        entity = new OfferCancelTransaction(rippleContext);
                        (entity as OfferCancelTransaction).UpdateEntity(data);
                        break;
                    }
                case "AccountSet":
                    {
                        entity = new AccountSetTransaction(rippleContext);
                        (entity as AccountSetTransaction).UpdateEntity(data);
                        break;
                    }
                case "SetRegularKey":
                    {
                        entity = new SetRegularKeyTransaction(rippleContext);
                        (entity as SetRegularKeyTransaction).UpdateEntity(data);
                        break;
                    }
                default:
                    {
                        // TODO: Replace with specific exception.
                        throw new Exception("Unknown transaction type " + data.tx.TransactionType);
                    }
            }

            entity.UpdateEntity(data);
            return entity;
        }

        internal static void UpdateEntity(this PaymentTransaction entity, TransactionData data)
        {
            if (data == null)
            {
                return;
            }

            entity.DestinationAccountId = data.tx.Destination;

            if (data.tx.Amount is string)
            {
                entity.Amount.Value = (data.tx.Amount as string).ToLong();
                entity.Amount.Currency = "XRP";
            }
            else
            {
                Dictionary<string, object> currency = (Dictionary<string, object>)data.tx.Amount;
                entity.Amount.Value = (currency["value"] as string).ToDouble();
                entity.Amount.Currency = currency["currency"] as string;
                entity.Amount.Issuer = currency["issuer"] as string;
            }
        }

        internal static void UpdateEntity(this TrustSetTransaction entity, TransactionData data)
        {
            if (data == null)
            {
                return;
            }

            entity.LimitAmount.Currency = data.tx.LimitAmount.currency;
            entity.LimitAmount.Value = data.tx.LimitAmount.value.ToDouble();
            entity.LimitAmount.Issuer = data.tx.LimitAmount.issuer;
        }

        internal static void UpdateEntity(this Transaction entity, TransactionData data)
        {
            if (data == null)
            {
                return;
            }

            entity.Id = data.tx.Hash;
            entity.AccountId = data.tx.Account;
            entity.Fee = data.tx.Fee.ToInt();
            entity.Date = data.tx.Date.ToDateTime();
            entity.Updated = DateTime.Now;
        }
    }
}